package com.zhourh.bang.modular.edu.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.zhourh.bang.common.persistence.dao.SScoreMapper;
import com.zhourh.bang.common.persistence.dao.SStudentMapper;
import com.zhourh.bang.common.persistence.dao.SSubjectMapper;
import com.zhourh.bang.common.persistence.model.SScore;
import com.zhourh.bang.common.persistence.model.SStudent;
import com.zhourh.bang.common.persistence.model.SSubject;
import com.zhourh.bang.core.util.DateUtil;
import com.zhourh.bang.core.util.PinYinUtil;
import com.zhourh.bang.core.util.ToolUtil;
import com.zhourh.bang.modular.edu.dto.UpScore;
import org.springframework.stereotype.Service;
import com.zhourh.bang.modular.edu.service.IScoreService;
import weka.core.*;
import weka.core.converters.ArffSaver;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * 成绩Service
 *
 * @author fengshuonan
 * @Date 2018-06-22 10:54:25
 */
@Service
public class ScoreServiceImpl implements IScoreService {

    @Resource
    private SStudentMapper studentMapper;

    @Resource
    private SSubjectMapper subjectMapper;

    @Resource
    private SScoreMapper scoreMapper;

    private String rule;

    @Override
    public int genScore() {
        List<SStudent> studentList = studentMapper.selectList(null);
        List<SSubject> subjectList = subjectMapper.selectList(null);
        int count = 0;
        if (studentList != null && !studentList.isEmpty() && subjectList != null && !subjectList.isEmpty()) {
            scoreMapper.delete(null);
            for (SSubject subject : subjectList) {
                int rdSTen = RandomUtil.randomInt(5, 8) * 10;
                int rdBTen = RandomUtil.randomInt(8, 11) * 10;
                for (SStudent student : studentList) {
                    SScore score = new SScore();
                    score.setStuId(student.getId());
                    score.setStuNo(student.getNo());
                    score.setStuName(student.getName());
                    score.setSubjectId(subject.getId());
                    score.setSubjectName(subject.getName());
                    score.setSubjectTerm(subject.getTerm());
                    score.setScore(RandomUtil.randomDouble(rdSTen, rdBTen));
                    score.insert();
                    count++;
                }
            }

        }
        return count;
    }

    @Override
    public Map<String, Object> getFormatScore() {
        Map<String, Object> result = new HashMap<>();
        //select all score list
        Wrapper<SScore> wrapper = new EntityWrapper<>();
        wrapper.orderBy("stuNo").orderBy("subjectId");
        List<SScore> scoreList = scoreMapper.selectList(wrapper);
        if (scoreList != null && !scoreList.isEmpty()) {
            String firstNo = scoreList.get(0).getStuNo();
            Map<String, Object> row = null;
            //define head
            Map<String, Object> headMap = null;
            List<Map<String, Object>> headList = new ArrayList<>();
            //define data
            List<Map<String, Object>> dataList = new ArrayList<>();
            for (SScore score : scoreList) {
                if (score.getStuNo().equals(firstNo)) {
                    //添加上一行
                    if (row != null) {
                        dataList.add(row);
                    }
                    //需要新的一行
                    row = new HashMap<>();
                    row.put("name", score.getStuName());
                    row.put("stuNo", score.getStuNo());
                }
                //add to head
                headMap = new HashMap<>();
                headMap.put("subId", score.getSubjectId());
                headList.add(headMap);
                //add to data
                row.put(score.getSubjectId().toString(), score.getScore());
            }
            result.put("table", headList);
            result.put("data", dataList);
        }
        return result;
    }


    /**
     * 格式化分数结果
     *
     * @return
     */
    List<Map<String, Object>> genFormatData() {
        //select all score list
        Wrapper<SScore> wrapper = new EntityWrapper<>();
        wrapper.orderBy("stuNo,subjectId");
        List<SScore> scoreList = scoreMapper.selectList(wrapper);
        //define data
        List<Map<String, Object>> dataList = new ArrayList<>();
        if (scoreList != null && !scoreList.isEmpty()) {
            String firstNo = scoreList.get(0).getStuNo();
            HashMap<String, Object> row = null;
            for (SScore score : scoreList) {
                if (row == null || !score.getStuNo().equals(firstNo)) {
                    firstNo = score.getStuNo();
                    //添加上一行
                    if (row != null) {
                        dataList.add(row);
                    }
                    //需要新的一行
                    row = new HashMap<>();
                }
                //add to data
//                row.put(PinYinUtil.getPingYin(score.getSubjectName().trim()), getMapForScore(score.getScore()));
                row.put(score.getSubjectName().trim(), getMapForScore(score.getScore()));
            }
        }
        return dataList;
    }

    Instances genInstances(Integer minRangeNum) {
        if(minRangeNum==null || minRangeNum<1){
            minRangeNum=1;
        }
        List<Map<String, Object>> scoreList = genFormatData();
        //set attributes
        ArrayList<Attribute> attributes = new ArrayList<>();
        if (scoreList != null && !scoreList.isEmpty()) {
            //
            Map<String, Object> map = scoreList.get(0);
            Set<String> keys = new HashSet<>();
            for (Map.Entry entry : map.entrySet()) {
                keys.add((String) entry.getKey());
            }

            Map<String, List<String>> keyValue = new HashMap<>();
            for (String key : keys) {
                Set<String> valueSet = new HashSet<>();
                for (Map<String, Object> score : scoreList) {
                    String value = (String) score.get(key);
                    valueSet.add(value);
//                    System.out.println("key:" + key + " value:" + value);
                }
                if(!valueSet.isEmpty() && valueSet.size()>=minRangeNum){
                    List<String> valueList = new ArrayList<>(valueSet);
                    keyValue.put(key,valueList);
                }
            }
            for (Map.Entry entry : keyValue.entrySet()) {
                String key = (String) entry.getKey();
                System.out.println(key +  " - values : " + keyValue.get(key));
                attributes.add(new Attribute(key, keyValue.get(key)));
            }
            Instances instances = new Instances("repo_score", attributes, 0);
            instances.setClassIndex(instances.numAttributes() - 1);
            if (!scoreList.isEmpty()) {
                int index = 0;
                for (Map<String, Object> map4data : scoreList) {
                    index = 0;
                    Instance instance = new DenseInstance(attributes.size());
                    instance.setDataset(instances);
                    for (Map.Entry entry : map4data.entrySet()) {
                        String key = (String) entry.getKey();
                        System.out.println("Subject: " + key);
                        if(keyValue.get(key)!=null){
                            instance.setValue(index, (String) entry.getValue());
                            index++;
                        }
                    }
                    instances.add(instance);
                }
            }
            return instances;
        }
        return null;
    }

    /**
     * 获取离散分数段 如A90-100 B80-90
     */
    String getMapForScore(Double score) {
        if (!ToolUtil.isOneEmpty(this.rule, score)) {
            String[] rules = this.rule.split(",");
            if (rules.length > 0) {
                for (int i = 0; i < rules.length; i++) {
                    String[] range = rules[i].split(":");
                    if (range.length > 0) {
                        String[] scores = range[1].split("-");
                        if (scores.length > 0) {
                            Integer score1 = Integer.valueOf(scores[0]);
                            Integer score2 = Integer.valueOf(scores[1]);
                            if ((score >= score1 && score <= score2) || (score >= score2 && score <= score1)) {
//                                System.out.println("ScoreMapping : " + range[0].toUpperCase());
                                return range[0].toUpperCase();
                            }
                        }
                    }
                }
            }
        }
        return "Z";
    }

    @Override
    public String genFormatFile(String fileName, String rule, Integer minRangeNum) {
        this.rule = rule;
        Instances instances = genInstances(minRangeNum);
        ArffSaver saver = new ArffSaver();
        saver.setInstances(instances);
        if (ToolUtil.isOneEmpty(fileName)) {
            fileName = DateUtil.getAllTime();
        }
        try {
            String path = FileUtil.getWebRoot() + File.separator + "arff" + File.separator + DateUtil.getAllTime() + ".arff";
            System.out.println(path);
            saver.setFile(new File(path));
            saver.writeBatch();
            return path;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 上传成绩
     */
    @Override
    public int uploadScore(List<UpScore> scores){
        int count = 0;
        if(scores!=null && scores.size()>0){
            //插入新数据先删除原有数据
            scoreMapper.delete(null);
            //do for
            for (UpScore score : scores){
                if(score.getScore()==null || score.getScore()>100 || score.getScore()<0){
                    score.setScore(0.0);
                }
                SStudent sStudent = new SStudent();
                sStudent.setNo(score.getNo());
                SSubject sSubject = new SSubject();
                sSubject.setName(score.getSubject().trim());
                SStudent student = studentMapper.selectOne(sStudent);
                SSubject subject = subjectMapper.selectOne(sSubject);
                if(student!=null){
                    SScore sScore = new SScore();
                    sScore.setStuNo(score.getNo());
                    sScore.setStuId(student.getId());
                    sScore.setStuName(student.getName());
                    sScore.setScore(score.getScore());
                    sScore.setSubjectId(subject.getId());
                    sScore.setSubjectName(score.getSubject().trim());
                    sScore.setSubjectTerm(Integer.valueOf(score.getTerm()));
//                    System.out.println(sScore);
                    if(sScore.insert()){
                        System.out.println("插入数量：" + count++);
                    }
                }
            }
        }
        return count;
    }

}
